home *** CD-ROM | disk | FTP | other *** search
- /***********************************************\
- * *
- * simgeo.c = Geometric Operations for SIMPP: *
- * Simple IMage Processing Package. *
- * Copyright (c) 1987, Benjamin M. Dawson *
- * Edit Version: 1.2 : Jan-30-87 *
- * *
- \***********************************************/
-
- #include "simpp.h"
-
- extern char *malloc();
-
- /* rotate = Rotate clockwise by 90 degrees. Limited to an area of MEMSIZE,
- * and should be a square area.
- */
- int rotate(x,y,dx,dy)
- register int x,y; /* Start of area to rotate */
- int dx,dy; /* Size of area to rotate */
- {
- register int i;
- unsigned long nl;
- PIXEL *buf, *bp;
-
- #ifdef CHECK
- if (check_area(x,y,dx,dy,"<rotate>") == ERROR)
- return(ERROR);
- #endif
-
- /* Compute the number of bytes in the image area to be rotated */
- nl = ((long)dx)*((long)dy)*((long)sizeof(PIXEL));
- #ifdef CHECK
- if (nl > MEMSIZE) {
- printf("<rotate> Area too large!\n");
- return(ERROR);
- }
- if (dx != dy) {
- printf("(rotate) Warning: area not square, may write\n");
- printf(" outside of the image memory!\n");
- }
- #endif
- /* Allocate a large buffer for storage */
- buf = bp = (PIXEL *)malloc(((unsigned int)nl));
-
- /* Read in image */
- if (read_area(x,y,dx,dy,bp) == ERROR) {
- printf("<rotate> Can't read area!\n");
- return(ERROR);
- }
-
- /* Write it out the other way */
- while (dy--) {
- for (i = 0 ; i < dx ; i++) write_pixel(x,y+i,*bp++);
- x++;
- }
-
- free(buf);
- return(OK);
- }
-
- /* ================================================================ */
-
- /* stretch = Enlarge image size by stretching the image by xs,ys.
- * The image is stretched into the same area, starting from the
- * upper,left corner. Limited to a MEMSIZE area, and uses interpolation
- * to smooth pixel values.
- */
- stretch(x,y,dx,dy,xs,ys)
- int x,y; /* Start of source AND destination */
- int dx,dy; /* Size of Source AND destination */
- double xs,ys; /* X,Y scale factors */
- {
- register int i,j;
- int ix,iy;
- unsigned long nl;
- PIXEL *buf, *bp, *p;
- double A,B,C,D,xAB,xCD,xx,yy,V;
-
- #ifdef CHECK
- if (check_area(x,y,dx,dy,"<stretch>") == ERROR)
- return(ERROR);
-
- /* Must stretch -- shrinking will cause indexing problems */
- if ((xs < 1.0) || (ys < 1.0)) {
- printf("<stretch> Scale factors must be > 1.0!\n");
- return(ERROR);
- }
- #endif
-
- nl = ((long)dx)*((long)dy);
- #ifdef CHECK
- if (nl > MEMSIZE) {
- printf("<stretch> Area too large!\n");
- return(ERROR);
- }
- #endif
-
- buf = bp = (PIXEL *)malloc((unsigned int)nl*sizeof(PIXEL));
- if (read_area(x,y,dx,dy,bp) == ERROR) return(ERROR);
-
- /* Method: We compute fractional addresses (xx,yy) that indicate where
- * the source "pixel" would be. Since this address, in general, will fall
- * between pixels, we approximate the value by bi-linear interpolation.
- * We round the fractional addresses down to integer values to get the
- * address (ix,iy) of nearest real pixel to the top and left of the desired
- * "interpolated pixel". We then subtract this address from the interpolated
- * pixel address to get the fraction of address between the four pixels
- * surrounding the interpolated pixel (xx = xx - ix, yy = yy -iy). The
- * address of the nearest top, left pixel (called pixel A) is incremented
- * to get pixel values for the four pixels surrounding the interpolated
- * pixel. Thus we have a 2 by 2 matrix of values:
- * A B
- * C D
- * To get the interpolated value, we first compute the linear weighted
- * value at distance xx between A and B and at xx between C and D. These
- * two values (yAB and yCD) are weighted by yy to get the interpolated
- * value.
- */
- /* Compute address of the "interpolated pixel" and the nearest real pixel */
- for (i = 1 ; i < dy ; i++) { /* Don't change first row */
- yy = (double)(i-1)/ys; /* Compute y address for source */
- iy = (int)yy; /* Round to integer */
- yy = yy - (double)iy; /* Leave only fraction of address */
- bp = buf + iy*dx; /* Compute pointer to nearest line */
- for (j = 1 ; j < dx ; j++) { /* Don't change first column */
- xx = (double)(j-1)/xs; /* Compute x address for source */
- ix = (int)xx; /* Rount to integer */
- xx = xx - (double)ix; /* Leave only fraction of address */
- /* Compute the value of the four nearest neighbor pixels */
- p = bp + ix; /* Pointer to top, left real pixel */
- A = (double)(*p++); /* Top, left real pixel */
- B = (double)(*p); /* Top, right real pixel */
- D = (double)(*(p + dx));/* Bottom, right real pixel */
- C = (double)(*(p + dx - 1)); /* Bottom, left real pixel */
- /* Compute the linear interpolated values (A to B and C to D) */
- xAB = A + (B - A)*xx; /* xx of the way between A and B */
- xCD = C + (D - C)*xx; /* xx of the way between C and D */
- /* Compute the (bi)linear interpolated value between xAB and xCD. This is
- * yy of the way between xAB and xCD. Round the value by adding 0.5 */
- V = xAB + ((xCD - xAB)*yy) + 0.5;
- /* Write out interpolated value */
- write_pixel(x+j,y+i,(PIXEL)V);
- }
- }
-
- free(buf);
- return(OK);
- }
-
- /* ================ End of simgeo.c ================ */
-
- /* <-- FILE BREAK --> */